package com.locus.tools.xmpp;

import android.content.*;

import android.content.IntentFilter.MalformedMimeTypeException;
import android.os.*;

import com.google.android.gtalkservice.*;
import com.locus.tools.LocusConstants;

/**
 * Implements a persistent connection agent to the XMPP protocol for any 
 * contact. Allows any class to connect to it, send messages along with a 
 * IRecievable message reciever, which will parse the returned message and give 
 * it back to the sending class.
 * <p>
 * Completely redesigned as of May 25, 2008.
 *
 * 
 * @author jfredett
 *
 */
public class GTalkAgent {
	IGTalkService gtalkservice;
	IGTalkSession session;
	Context context;
	/**
	 * the GUID of the message. Static across all types.
	 */
	static Integer GUID;

	/**
	 * Connect to the gtalkService at construction time.
	 * @param context
	 * @throws GTalkFailedException
	 */
	public GTalkAgent(Context context) throws GTalkFailedException {
		try {
			session = gtalkservice.getDefaultSession();
		} catch (DeadObjectException e) {
			throw new GTalkFailedException("Default Session Doesn't Exist.");
		}
		this.context = context;
	}

	/**
	 * Sends a message to the Recipient specified in the ISendable implementing message
	 * class
	 * @param message <br>
	 * 	the message to be sent.
	 * @return <br> 
	 * 	an intent filter for the message.
	 * @throws GTalkFailedException
	 * 	if something goes wrong while trying to send the message
	 * @throws MalformedMimeTypeException 
	 *  if something goes wrong while creating the filter.
	 */
	public IntentFilter sendMessage(ISendable message)
	throws GTalkFailedException, MalformedMimeTypeException {
		try {
			// MIME Type for use in identifying the message
			String MIME = LocusConstants.MIME_XMPP(getNextGUID().toString());

			// construct the message intent
			
			/* this is old stuff, we changed the ISendable interface to give us a method to do this OTF.
			Intent sendableMessage = new Intent();
			sendableMessage.setType(MIME);
			sendableMessage.addCategory("GTalk");
			sendableMessage.putExtra(LocusConstants.MSG_FIELD, message.getMessage());
			sendableMessage.putExtra(LocusConstants.TO_FIELD, message.getSender());
			sendableMessage.putExtra(LocusConstants.FROM_FIELD, message.getRecipient());
			*/
			
			// create the intent, override the mime-type, we'll need this later for the filter.
			Intent sendableMessage = message.createIntent();
			sendableMessage.setType(MIME);
			sendableMessage.addCategory("GTalk");
			
			// send it
			session.sendDataMessage(message.getRecipient(), sendableMessage);

			// create an Intentreciever to catch the message later.
			IntentFilter filter = new IntentFilter();
			filter.addCategory("GTalk");
			filter.addDataType(MIME);
			return filter;
		}

		catch (DeadObjectException doe) {
			throw new GTalkFailedException("Could not send message due to: \n\n\n" + doe.getMessage());
		}
	}

	/**
	 * Gets a message from the pool, designed to be used with the filter generated by
	 * the sendMessage method in this class.
	 * @param messageHolder <br>
	 * 	a IRecievable class which will store the returned message.
	 * @param filter <br>
	 *  the filter for the Intent Pool.
	 * @return <br>
	 *  the messageHolder class with the message stored in the Intent.
	 */
	public IRecievable getMessage(IRecievable messageHolder, IntentFilter filter) {
		// get the intent from the pool.
		Intent recieved = context.registerReceiver(null, filter);
		// now, if the intent recieved is 
		if (recieved.getCategories().contains("GTalk")) {
			messageHolder.createRecievable(recieved.getStringExtra("From"), recieved.getStringExtra("Message"),
					recieved.getStringExtra("To"));
		}
		return messageHolder;
	}

	/* ********************** */
	/* ********************** */
	/* ********************** */

	private Integer getNextGUID() {
		return (GUID++);
	}

}
